package com.arpa.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.cache.PartyGroupCache;
import com.arpa.ntocc.common.common.cache.ShipmentCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.service.IOmsInboundService;
import com.arpa.oms.service.IOmsInventoryService;
import com.arpa.wms.cache.*;
import com.arpa.wms.common.util.OrderIdGeneratorUtil;
import com.arpa.wms.domain.consts.CommonConst;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.dto.*;
import com.arpa.wms.domain.entity.*;
import com.arpa.wms.domain.enums.*;
import com.arpa.wms.domain.vo.*;
import com.arpa.wms.mapper.PutawayMapper;
import com.arpa.wms.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.qimen.api.DefaultQimenClient;
import com.qimen.api.QimenClient;
import com.qimen.api.request.EntryorderConfirmRequest;
import com.qimen.api.request.ReturnorderConfirmRequest;
import com.qimen.api.response.EntryorderConfirmResponse;
import com.qimen.api.response.ReturnorderConfirmResponse;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.arpa.wms.domain.consts.CommonConst.LOT_NUMBER;
import static com.arpa.wms.domain.consts.NumConst.NUM_ONE;
import static com.arpa.wms.domain.consts.NumConst.NUM_ZERO;

//import com.arpa.wms.mq.provider.InboundConfirmSender;
//import com.arpa.wms.mq.provider.ReturnInboundConfirmSender;

/**
 * <p>
 * 上架 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-08-04
 */
@Service
@Log4j2
public class PutawayServiceImpl extends ServiceImpl<PutawayMapper, Putaway> implements IPutawayService {

    @Value("${taobao.qimen.url}")
    private String url;
    @Value("${taobao.qimen.appkey}")
    private String appkey;
    @Value("${taobao.qimen.secret}")
    private String secret;

    @Autowired
    private ShipmentCache shipmentCache;
    @Autowired
    private GoodsCache goodsCache;
    @Autowired
    private WarehouseCache warehouseCache;
    @Autowired
    private PartyCache partyCache;
    @Autowired
    private BatchRuleCache batchRuleCache;
    @Autowired
    private SupplierCache supplierCache;
    @Autowired
    private PartyGroupCache partyGroupCache;
    @Autowired
    private LocationCache locationCache;
    @Autowired
    private IPutawayItemService iPutawayItemService;
    @Autowired
    private IPutawayRegisterService iPutawayRegisterService;
    @Autowired
    @Lazy
    private IReceiveService iReceiveService;
    @Autowired
    private IReceiveItemService iReceiveItemService;
    @Autowired
    @Lazy
    private IReceiveRegisterService iReceiveRegisterService;
    @Autowired
    private IInboundService iInboundService;
    @Autowired
    private IInboundItemService iInboundItemService;
    @Autowired
    private IInventoryService iInventoryService;
    @Autowired
    private IInventoryRecordService iInventoryRecordService;
    @Autowired
    private ILocationService iLocationService;
    @Autowired
    private IContainerService iContainerService;
    @Autowired
    @Lazy
    private IWmsTaskService iWmsTaskService;
    @Autowired
    @Lazy
    private IWmsTaskItemService iWmsTaskItemService;

    @Autowired
    @Lazy
    private IWmsTaskItemService wmsTaskItemService;
    @Autowired
    private GoodsUnitConversionCache goodsUnitConversionCache;

    @Autowired
    private IExpenseDetailService iExpenseDetailService;

    @Autowired
    private IContractService iContractService;

    @Autowired
    @Lazy
    private IOmsInboundService iOmsInboundService;

    @Autowired
    private IOmsInventoryService iOmsInventoryService;


    @Autowired
    private IGoodsPnService goodsPnService;
    //@Autowired
    //private InboundConfirmSender inboundConfirmSender;
    //
    //@Autowired
    //private ReturnInboundConfirmSender returnInboundConfirmSender;



    /**
     * 保存
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public boolean save(Putaway entity) {
        if(StringUtils.isBlank(entity.getCode())){
            entity.setCode(IdUtil.simpleUUID());
        }
        if(StringUtils.isBlank(entity.getCreatedBy())){
            entity.setCreatedBy(UserUtil.getCode());
            entity.setCreatedName(partyCache.translate(entity.getCreatedBy()));
        }
        entity.setModifiedBy(UserUtil.getCode());
        entity.setModifiedName(partyCache.translate(entity.getCreatedBy()));

        return super.save(entity);
    }

    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(Putaway entity) {
        if(StringUtils.isBlank(entity.getModifiedBy())){
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(entity.getModifiedBy()));
        }
        return baseMapper.update(entity,new QueryWrapper<Putaway>().lambda().eq(Putaway::getCode,entity.getCode()).eq(Putaway::getGroupCode,UserUtil.getBranchCode()));
    }

    /**
     * 查询列表
     * @param putawayDTO
     * @return
     */
    @Override
    public List<PutawayVO> queryList(PutawayDTO putawayDTO){
        putawayDTO.setGroupCode(UserUtil.getBranchCode());
        //排序字段名需要驼峰转数据库下划线类型字段名
        if(StringUtils.isNotEmpty(putawayDTO.getSortField())){
            putawayDTO.setSortField(CommonUtil.camel2Underline(putawayDTO.getSortField()));
        }
        if ("warehouse_name".equals(putawayDTO.getSortField())){
            putawayDTO.setSortField("a.warehouse_code");
        }
        List<PutawayVO> putawayVOList = baseMapper.queryList(putawayDTO);
        // 翻译
        putawayVOList.stream().forEach(e->{
            e.setWarehouseName(warehouseCache.translate(e.getWarehouseCode()));
            e.setShipmentName(shipmentCache.translate(e.getShipmentCode()));
        });

        return putawayVOList;
    }

    /**
     * 查询合计,包含总数
     * @param putawayDTO
     * @return
     */
    @Override
    public PutawayVO queryListSum(PutawayDTO putawayDTO){
        putawayDTO.setGroupCode(UserUtil.getBranchCode());
        if (IterUtil.isEmpty(putawayDTO.getShipmentCodes())) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        sb.append("SELECT ");
        putawayDTO.getShipmentCodes().stream().forEach(e -> {
            sb.append("(SELECT count(*) AS total FROM `wms_putaway`  WHERE 1=1 ");
            if (StrUtil.isNotEmpty(putawayDTO.getWarehouseCode())) {
                sb.append("and `warehouse_code` ='" + putawayDTO.getWarehouseCode());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getGroupCode())) {
                sb.append("' and `group_code` ='" + putawayDTO.getGroupCode());
            }
            sb.append("' and `shipment_code` =  '" + e);
            if (ObjectUtil.isNotEmpty(putawayDTO.getDeleted())) {
                sb.append("' and `is_deleted` ='" + putawayDTO.getDeleted());
            } else {
                sb.append("' and `is_deleted` =  '" + NUM_ZERO);
            }

            if (StrUtil.isNotEmpty(putawayDTO.getCode())) {
                sb.append("' and `code` like'%" + putawayDTO.getCode()+"%");
            }
            if (StrUtil.isNotEmpty(putawayDTO.getReceiveCode())) {
                sb.append("' and `receive_code` ='" + putawayDTO.getReceiveCode());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getShipmentName())) {
                sb.append("' and `shipment_name` like'%" + putawayDTO.getShipmentName() +"%");
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getPutawayQuantity())) {
                sb.append("' and `putaway_quantity` ='" + putawayDTO.getPutawayQuantity());
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getTotalQuantity())) {
                sb.append("' and `total_quantity` ='" + putawayDTO.getTotalQuantity());
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getPutawayQuantity())) {
                sb.append("' and `putaway_quantity` ='" + putawayDTO.getPutawayQuantity());
            }

            if (StrUtil.isNotEmpty(putawayDTO.getStatus())) {
                sb.append("' and `status` ='" + putawayDTO.getStatus());
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getIssue())) {
                sb.append("' and `is_issue` ='" + putawayDTO.getIssue());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getRemarks())) {
                sb.append("' and `remarks` ='" + putawayDTO.getRemarks());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getId())) {
                sb.append("' and `id` ='" + putawayDTO.getId());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getCreatedBy())) {
                sb.append("' and `created_by` ='" + putawayDTO.getCreatedBy());
            }

            if (ObjectUtil.isNotEmpty(putawayDTO.getGmtCreated())) {
                sb.append("' and `gmt_created` ='" + putawayDTO.getGmtCreated());
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getModifiedBy())) {
                sb.append("' and `modified_by` ='" + putawayDTO.getModifiedBy());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getModifiedName())) {
                sb.append("' and `modified_name` ='" + putawayDTO.getModifiedName());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getCreatedName())) {
                sb.append("' and `created_name` ='" + putawayDTO.getCreatedName());
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getGmtCreatedStart()) && ObjectUtil.isNotEmpty(putawayDTO.getGmtCreatedEnd())) {
                sb.append("' and `gmt_created` between '" + putawayDTO.getGmtCreatedStart() + "' and '" + putawayDTO.getGmtCreatedEnd());
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getGmtModifiedStart()) && ObjectUtil.isNotEmpty(putawayDTO.getGmtModifiedEnd())) {
                sb.append("' and `gmt_modified` between '" + putawayDTO.getGmtModifiedStart() + "' and '" + putawayDTO.getGmtModifiedEnd());
            }

            if (ObjectUtil.isNotEmpty(putawayDTO.getTotalQuantityStart()) && ObjectUtil.isNotEmpty(putawayDTO.getTotalQuantityEnd())) {
                sb.append("' and `total_quantity` between '" + putawayDTO.getTotalQuantityStart() + "' and '" + putawayDTO.getTotalQuantityEnd());
            }
            if (ObjectUtil.isNotEmpty(putawayDTO.getPutawayQuantityStart()) && ObjectUtil.isNotEmpty(putawayDTO.getPutawayQuantityEnd())) {
                sb.append("' and `putaway_quantity` between '" + putawayDTO.getPutawayQuantityStart() + "' and '" + putawayDTO.getPutawayQuantityEnd());
            }

            if (ObjectUtil.isNotEmpty(putawayDTO.getIssue())) {
                sb.append("' and `is_issue` ='" + putawayDTO.getIssue());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getRemarks())) {
                sb.append("' and `remarks` ='" + putawayDTO.getRemarks());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getId())) {
                sb.append("' and `id` ='" + putawayDTO.getId());
            }
            if (StrUtil.isNotEmpty(putawayDTO.getCreatedBy())) {
                sb.append("' and `created_by` ='" + putawayDTO.getCreatedBy());
            }
            sb.append("') +");
        });
        sb.replace(sb.length() - 1, sb.length(), "");
        sb.append("AS total ");

        return this.baseMapper.queryListSum(sb.toString());
    }

    /**
     * 查询合计,包含总数
     * @param putawayDTO
     * @return
     */
    @Override
    public PutawayVO queryListTotal(PutawayDTO putawayDTO){
        return this.baseMapper.queryListTotal(putawayDTO);
    }

    /**
     * @description 上架单保存
     *
     * @author xuyang
     * @date 2020/9/27 8:35
     **/
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result localSave(Putaway entity) {
        entity.setGroupCode(UserUtil.getBranchCode());
        savePutawayAndItem(entity, StrUtil.EMPTY, PutawayItemStatusEnum.WAITING.getValue());

        return Result.ok("保存成功");
    }



    /**
     * @description 保存上架单及明细
     * PC端本地保存
     * @author xuyang
     * @date 2020/9/27 8:27
     **/
    @Transactional(rollbackFor = Exception.class)
    public List<PutawayRegister> savePutawayAndItem(Putaway entity, String putawayStatus, String putawayRegisterStatus){
        String groupCode = entity.getGroupCode();
        Putaway putaway = this.getOne(new QueryWrapper<Putaway>().lambda()
                .eq(Putaway::getCode, entity.getCode())
                .eq(Putaway::getGroupCode,groupCode)
                .eq(Putaway::getDeleted, "0"));
        // 判断是否可以保存
        if (null==putaway) {
            throw new ServiceException("上架单不存在，请确认。");
        }
        if(!StrUtil.equalsAny(putaway.getStatus(), PutawayStatusEnum.WAITING_PUTAWAY.getValue(), PutawayStatusEnum.PUTAWAYING.getValue())){
            throw new ServiceException("上架单状态不正确，请确认。");
        }

        List<PutawayItemWithRegisterVO> putawayItems = entity.getPutawayRegisterWithItemVOS();
        // 判断托盘是否被拆分放到不同的库位上了
        checkContainer(putawayItems);

        // 过滤前端数据，只留下未上架确认的数据
        List<PutawayRegister> unSaveRegisters = Collections.emptyList();
        if(IterUtil.isNotEmpty(putawayItems)) {
            unSaveRegisters = putawayItems.stream()
                    .filter(e->!PutawayItemStatusEnum.FINISH.getValue().equals(e.getStatus()))
                    .map(e->{
                        PutawayRegister register = new PutawayRegister();
                        BeanUtil.copyProperties(e, register);
                        register.setCode(IdUtil.simpleUUID());
                        register.setCreatedBy(UserUtil.getCode());
                        register.setPutawayCode(entity.getCode());
                        register.setStatus(putawayRegisterStatus);
                        register.setDeleted(0);
                        register.setGroupCode(groupCode);
                        return register;
                    }).collect(Collectors.toList());
        }

        unSaveRegisters.forEach(e->{
            if(ObjectUtil.isNull(e.getPutawayQuantity()) || e.getPutawayQuantity().compareTo(BigDecimal.ZERO) < NUM_ZERO){
                throw new ServiceException("上架数量必须大于0！");
            }
            e.setLocation(StrUtil.blankToDefault(e.getLocation(), StrUtil.EMPTY));
        });

        // 查询数据库中相同状态的数据，并合并未保存的数据；
        //List<PutawayRegister> allRegisters = iPutawayRegisterService.list(new QueryWrapper<PutawayRegister>().lambda()
        //        .eq(PutawayRegister::getPutawayCode, entity.getCode())
        //        .eq(PutawayRegister::getStatus, putawayRegisterStatus));
        //allRegisters.addAll(unSaveRegisters);

        // 删除数据库中未上架确认的数据
        iPutawayRegisterService.remove(new QueryWrapper<PutawayRegister>().lambda().eq(PutawayRegister::getPutawayCode, entity.getCode())
                .eq(PutawayRegister::getGroupCode,groupCode)
                .in(PutawayRegister::getStatus, PutawayItemStatusEnum.WAITING.getValue(), PutawayItemStatusEnum.PUTAWAYING.getValue()));

        // 由于会存在新上架的信息会合并到老数据上，所以返回时的列表不一定都是新建的register
        List<PutawayRegister> newSavedRegisters = new ArrayList<>();
        // 保存当前未确认上架信息, 保存时，需要合并相同数据
        unSaveRegisters.forEach(e->{
            // 查询数据库中是否存在 已上架、 相同明细号（相同商品）、 相同库位的确认单
            PutawayRegister sameRegister = iPutawayRegisterService.getOne(new QueryWrapper<PutawayRegister>().lambda()
                    .eq(PutawayRegister::getStatus, putawayRegisterStatus)
                    .eq(PutawayRegister::getGroupCode,groupCode)
                    .eq(PutawayRegister::getPutawayItemCode, e.getPutawayItemCode())
                    .eq(PutawayRegister::getLocation, e.getLocation()));
            if(sameRegister != null){
                // 给空数量一个默认值
                BigDecimal addQuantity = e.getPutawayQuantity() == null? BigDecimal.ZERO:e.getPutawayQuantity();
                iPutawayRegisterService.update(new UpdateWrapper<PutawayRegister>().lambda()
                        .eq(PutawayRegister::getGroupCode,groupCode)
                        .eq(PutawayRegister::getCode, sameRegister.getCode())
                    .setSql(" putaway_quantity = putaway_quantity + " + addQuantity));
                // 数据库中已有老的上架数据，则返回的未上架信息是老的，但上架数量需要使用新的，否则会上架多了
                sameRegister.setPutawayQuantity(addQuantity);
                newSavedRegisters.add(sameRegister);
            }else{
                iPutawayRegisterService.save(e);
                newSavedRegisters.add(e);
            }
        });
        // 保存主单
        if(StrUtil.isNotEmpty(putawayStatus)) {
            putaway.setStatus(putawayStatus);
        }
        putaway.setRemarks(entity.getRemarks());
        putaway.setOperatorName(entity.getOperatorName());
        this.updateByCode(putaway);

        // 更新子单上架数量
        iPutawayItemService.updateRegisterQuantity(putaway.getCode(), PutawayItemStatusEnum.FINISH.getValue());
        // 更新主单上架数量
        this.updateRegisterQuantity(putaway.getCode(), PutawayItemStatusEnum.FINISH.getValue());

        return newSavedRegisters;
    }

    /**
     * @description
     * 检查托盘容器是否存在拆分出多个确认单，不能存在一个托盘上架多个库位的情况
     * @author xuyang
     * @date 2020/10/21 11:30
     * @param putawayItems:
     * @return com.arpa.core.web.Result
     **/
    private void checkContainer(final List<PutawayItemWithRegisterVO> putawayItems) {
        // 被放到不同库位的托盘容器号列表
        List<String> errorContainerBarCodes = new ArrayList<>();
        if(IterUtil.isNotEmpty(putawayItems)) {
            // 过滤掉非托盘
            List<PutawayItemWithRegisterVO> registers = putawayItems.stream().filter(e->ContainerTypeEnum.PALLET.getValue().equals(e.getContainerType()))
                    .collect(Collectors.toList());

            // 用于判断是否有相同托盘、但不同库位的临时map
            Map<String, String> temp;
            temp = new HashMap<>();
            registers.forEach(e->{
                if(temp.containsKey(e.getContainerBarCode()) && !temp.get(e.getContainerBarCode()).equals(e.getLocation())){
                    errorContainerBarCodes.add(e.getContainerBarCode());
                }else{
                    temp.put(e.getContainerBarCode(), e.getLocation());
                }
            });
        }

        if (!IterUtil.isEmpty(errorContainerBarCodes)) {
            throw new ServiceException("托盘容器" + errorContainerBarCodes.stream()
                    .map(e->StrUtil.wrap(e, "\""))
                    .collect(Collectors.joining(",")) + "不允许上架到不同的库位上");
        }

    }

    /**
     * 确认上架信息
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Inbound check(Putaway entity) {
        String groupCode = UserUtil.getBranchCode();
        String creator = UserUtil.getCode();
        String creatorName = partyCache.translate(creator);
        entity.setGroupCode(groupCode);
        // 校验上架信息
        validatePCCheckInfo(entity);

        // 保存主单及明细， 返回新保存的确认单
        List<PutawayRegister> newPutawayRegisters = savePutawayAndItem(entity,
                PutawayStatusEnum.FINISH_PUTAWAY.getValue(),
                PutawayItemStatusEnum.FINISH.getValue());

        // 获取数据库中最新数据，用于生成入库单、库存等
        entity = this.getOne(new QueryWrapper<Putaway>().lambda().eq(Putaway::getCode, entity.getCode()).eq(Putaway::getGroupCode,groupCode));
        List<PutawayRegister> registers = iPutawayRegisterService.list(new QueryWrapper<PutawayRegister>().lambda()
            .eq(PutawayRegister::getPutawayCode, entity.getCode())
                .eq(PutawayRegister::getGroupCode,groupCode)
                .eq(PutawayRegister::getStatus, PutawayItemStatusEnum.FINISH.getValue()));

        //  生成入库单信息
        Inbound inbound = generateAndSaveInboundInfo(entity, registers,creator,creatorName);

        // 生成库存
        if (IterUtil.isNotEmpty(newPutawayRegisters)) {
            generateAndSaveInventory(newPutawayRegisters);
        }

        // 根据上架单明细号去重
        List<PutawayRegister> uniqueRegister = newPutawayRegisters.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PutawayRegister::getPutawayItemCode))), ArrayList::new)
        );
        // 根据上架确认单信息，更新收货确认单、收货明细、收货单的上架信息和入库信息
        uniqueRegister.forEach(this::refreshReceivePutawayAndInboundQuantity);

        // 收货单在收货入库、更新入库数量后进行的操作，如回填oms单据等
        iReceiveService.afterInbound(entity);

        // 更新动碰次数
        updateLocationActionNum(registers);

        // 释放该上架单使用的所有周转箱
        putawayReleaseContainer(entity.getCode(), groupCode);
        // 将上架任务结束掉
        finishTask(entity);



        return inbound;
    }

    /**
     * PDA确认上架信息
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Inbound pdaCheck(Putaway entity) {
        String groupCode = entity.getGroupCode();
        String creator = UserUtil.getCode();
        String creatorName = partyCache.translate(creator);


        // 获取数据库中最新数据，用于生成入库单、库存等
        List<PutawayRegister> registers = iPutawayRegisterService.list(new QueryWrapper<PutawayRegister>().lambda()
                .eq(PutawayRegister::getPutawayCode, entity.getCode())
                .eq(PutawayRegister::getGroupCode,groupCode)
                .eq(PutawayRegister::getStatus, PutawayItemStatusEnum.FINISH.getValue()));

        //  生成入库单信息
        Inbound inbound = generateAndSaveInboundInfo(entity, registers,creator,creatorName);

        // 生成库存
        if (IterUtil.isNotEmpty(registers)) {
            generateAndSaveInventory(registers);
        }

        // 根据上架单明细号去重
        List<PutawayRegister> uniqueRegister = registers.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PutawayRegister::getPutawayItemCode))), ArrayList::new)
        );
        // 根据上架确认单信息，更新收货确认单、收货明细、收货单的上架信息和入库信息
        uniqueRegister.forEach(this::refreshReceivePutawayAndInboundQuantity);

        // 收货单在收货入库、更新入库数量后进行的操作，如回填oms单据等
        iReceiveService.afterInbound(entity);

        // 更新动碰次数
        updateLocationActionNum(registers);

        // 释放该上架单使用的所有周转箱
        putawayReleaseContainer(entity.getCode(),groupCode);
        // 将上架任务结束掉
        finishTask(entity);



        return inbound;
    }

    /**
     * @description
     * 完成任务操作
     * @author xuyang
     * @date 2020/10/30 19:05
     * @param entity:
     **/
    @Transactional(rollbackFor = {Exception.class})
    public void finishTask(Putaway entity) {
        String groupCode = entity.getGroupCode();
        // 更新作业量、 完成任务
        iWmsTaskService.putawayUpdateJobQuantity(entity.getCode(),groupCode);
        iWmsTaskService.update(new UpdateWrapper<WmsTask>().lambda().eq(WmsTask::getSourceCode, entity.getCode())
                .eq(WmsTask::getGroupCode,groupCode)
                .set(WmsTask::getJobStatus, WmsTaskJobStatusEnum.COMPLETED));

    }

    /**
     * 更新库位动碰次数
     * @param register
     */
    @Transactional(rollbackFor = {Exception.class})
    public void updateLocationActionNum(List<PutawayRegister> register){
        register.forEach(e->{
            iLocationService.updateActionNum(e.getLocation(), 1);
        });
    }

    /**
     * 释放容器
     * @param putawayCode
     */
    @Transactional(rollbackFor = {Exception.class})
    public void releaseContainer(String putawayCode,String groupCode) {
        // 释放所有周转箱容器
        boolean flag = iContainerService.batchReleaseContainerByPutaway(putawayCode, ContainerTypeEnum.PASS_BOX.getValue(),groupCode );
    }

    /**
     * 上架单释放容器
     * @param putawayCode
     */
    @Transactional(rollbackFor = {Exception.class})
    public void putawayReleaseContainer(String putawayCode,String groupCode) {
        //先查询初要更新的容器信息，然后再更新
        List<String> containerBarCodes = iPutawayRegisterService.list(new LambdaQueryWrapper<PutawayRegister>()
                .eq(PutawayRegister::getPutawayCode, putawayCode)
                .eq(PutawayRegister::getGroupCode, groupCode)
                .eq(PutawayRegister::getContainerType, ContainerTypeEnum.PASS_BOX.getValue())
        ).stream().map(PutawayRegister::getContainerBarCode).collect(Collectors.toList());
        if (IterUtil.isEmpty(containerBarCodes)) {
            return;
        }
        // 释放所有周转箱容器
        iContainerService.update(new LambdaUpdateWrapper<Container>()
                .in(Container::getBarCode,containerBarCodes)
                .eq(Container::getGroupCode, groupCode)
                .set(Container::getOccupy, CommonConst.STR_ZERO)
                .set(Container::getOccupyCode,StrUtil.EMPTY)
        );
    }

    /**
     * 通过上架单号获取上架单信息
     * @param code
     * @return
     */
    @Override
    public PutawayVO getVOByCode(final String code) {
        String groupCode = UserUtil.getBranchCode();
        //获取上架单主单信息
        Putaway entity = getOne(new QueryWrapper<Putaway>().lambda().eq(Putaway::getCode,code).eq(Putaway::getGroupCode,groupCode));
        PutawayVO putawayVO = new PutawayVO();
        BeanUtil.copyProperties(entity, putawayVO);

        PutawayItemDTO putawayItemDTO = new PutawayItemDTO();
        putawayItemDTO.setPutawayCode(entity.getCode());
        putawayItemDTO.setGroupCode(groupCode);
        //获取上架单明细信息
        List<PutawayItemVO> putawayItemVOS = iPutawayItemService.queryList(putawayItemDTO);
        //更新上架单下发信息 todo
     /*   if (1 == entity.getIssue()) {
            List<WmsTask> wmsTasks = iWmsTaskService.list(new LambdaQueryWrapper<WmsTask>().select(WmsTask::getCode).eq(WmsTask::getSourceCode, code).eq(WmsTask::getGroupCode, groupCode));
            List<String> taskCodes = wmsTasks.stream().map(WmsTask::getCode).collect(Collectors.toList());
            iWmsTaskItemService.list(new LambdaQueryWrapper<WmsTaskItem>().in(WmsTaskItem::getTaskCode, taskCodes));
        }*/
        putawayVO.setPutawayItemVOList(putawayItemVOS);
        //获取上架确认明细
        List<PutawayItemWithRegisterVO> putawayRegisterWithItemVOS = iPutawayItemService.queryItemWithRegisterList(putawayItemDTO);
        putawayRegisterWithItemVOS.forEach(e->
            {e.setStatusName(PutawayItemStatusEnum.translate(e.getStatus()));
                e.setPlanPutawayQuantity(e.getPutawayQuantity());
            }
        );
        //待上架状态赋值上架数量
        assignPutawayQuantity(putawayRegisterWithItemVOS);
        // 翻译
        putawayVO.setWarehouseName(warehouseCache.translate(putawayVO.getWarehouseCode()));
        putawayVO.setGroupName(partyGroupCache.translate(putawayVO.getGroupCode()));
        putawayVO.setPutawayRegisterWithItemVOS(putawayRegisterWithItemVOS);

        return putawayVO;
    }

    private void assignPutawayQuantity (List<PutawayItemWithRegisterVO> putawayRegisterWithItemVOS) {
        Map<String, List<PutawayItemWithRegisterVO>> mapList = putawayRegisterWithItemVOS.stream().collect(Collectors.groupingBy(PutawayItemWithRegisterVO::getPutawayItemCode));

        for (Map.Entry<String, List<PutawayItemWithRegisterVO>> entry : mapList.entrySet()) {
            //当有多条上架登记信息时
            if (entry.getValue().size() > 0) {

                List<PutawayItemWithRegisterVO> putawayItemWithRegisterVOS = entry.getValue();
                List<PutawayItemWithRegisterVO> waitingPutawayItemWithRegisterVOS = putawayItemWithRegisterVOS.stream().filter(e -> PutawayStatusEnum.WAITING_PUTAWAY.getValue().equals(e.getStatus())).collect(Collectors.toList());
                if (waitingPutawayItemWithRegisterVOS.size() == 0) {
                    return;
                }
                BigDecimal putawayQuantity = putawayItemWithRegisterVOS.stream().map(PutawayItemWithRegisterVO::getPutawayQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal totalPutaway = putawayItemWithRegisterVOS.get(NUM_ZERO).getReceivedQuantity();
                //待上架商量 = 总的收货数量 - 已经上架的数量
                BigDecimal waitingPutawayQuantity = totalPutaway.subtract(putawayQuantity);
                if (waitingPutawayItemWithRegisterVOS.get(NUM_ZERO).getPutawayQuantity().compareTo(BigDecimal.ZERO) == 0) {
                    Map<String, PutawayItemWithRegisterVO> map = putawayRegisterWithItemVOS.stream().collect(Collectors.toMap(PutawayItemWithRegisterVO::getCode, e  -> e));
                    PutawayItemWithRegisterVO putawayItemWithRegisterVO = MapUtil.get(map, waitingPutawayItemWithRegisterVOS.get(NUM_ZERO).getCode(), PutawayItemWithRegisterVO.class);
                    putawayItemWithRegisterVO.setPlanPutawayQuantity(waitingPutawayQuantity);
                }
            } else {
                PutawayItemWithRegisterVO putawayItemWithRegisterVO = putawayRegisterWithItemVOS.get(NUM_ZERO);
                if (putawayItemWithRegisterVO.getPutawayQuantity().compareTo(BigDecimal.ZERO) > 0) {
                    return;
                }
                //当上架状态为待上架（上架数量为0）时，将上架数量更新为收货数量
                putawayItemWithRegisterVO.setPlanPutawayQuantity(putawayItemWithRegisterVO.getReceivedQuantity());
            }
        }
    }

    /**
     * @description
     * PC端上架确认前的校验
     * @author xuyang
     * @date 2020/10/30 19:08
     * @param entity:
     **/
    private void validatePCCheckInfo(Putaway entity){
        String groupCode = entity.getGroupCode();
        // 判断上架单状态
        Putaway oldEntity = this.getOne(new QueryWrapper<Putaway>().lambda()
                .eq(Putaway::getCode, entity.getCode()).eq(Putaway::getGroupCode,groupCode));
        if(ObjectUtil.isNull(oldEntity)) {
            throw new ServiceException("上架单不存在，请确认。");
        }
        if(PutawayStatusEnum.FINISH_PUTAWAY.getValue().equals(oldEntity.getStatus())){
            throw new ServiceException("上架单已确认，不能重复确认。");
        }
        // 获取未保存的待上架数据
        List<PutawayRegister> unSaveRegisters = Collections.emptyList();
        if(IterUtil.isNotEmpty(entity.getPutawayRegisterWithItemVOS())) {
            unSaveRegisters = entity.getPutawayRegisterWithItemVOS().stream()
                    .filter(e->!PutawayItemStatusEnum.FINISH.getValue().equals(e.getStatus()))
                    .map(e->{
                        PutawayRegister register = new PutawayRegister();
                        BeanUtils.copyProperties(e, register);
                        return register;
                    }).collect(Collectors.toList());

            // 校验数据是否填写上架数量、库位号
            for(PutawayRegister e: unSaveRegisters){
                if(e.getPutawayQuantity() == null || e.getPutawayQuantity().compareTo(BigDecimal.ZERO) <= 0){
                    throw new ServiceException("上架数量需要大于0");
                }
                if(StrUtil.isBlank(e.getLocation())){
                    throw new ServiceException("请选择上架库位");
                }
            }
        }
        // 获取数据库中已上架确认单
        List<PutawayRegister> allRegisters = iPutawayRegisterService.list(new QueryWrapper<PutawayRegister>().lambda()
                .eq(PutawayRegister::getPutawayCode, entity.getCode())
                .eq(PutawayRegister::getGroupCode,groupCode)
                .eq(PutawayRegister::getStatus, PutawayItemStatusEnum.FINISH.getValue()));
        // 合并所有上架确认单
        allRegisters.addAll(unSaveRegisters);
        // 获取上架明细单列表
        List<PutawayItem> items = iPutawayItemService.list(new QueryWrapper<PutawayItem>().lambda()
                .eq(PutawayItem::getPutawayCode, entity.getCode()).eq(PutawayItem::getGroupCode,groupCode));


        // 根据上架明细汇总上架数量
        Map<String, BigDecimal> itemPutawayQuantity;
        itemPutawayQuantity = new HashMap<>();
        allRegisters.forEach(e->{
            itemPutawayQuantity.put(e.getPutawayItemCode(), itemPutawayQuantity.getOrDefault(e.getPutawayItemCode(), BigDecimal.ZERO).add(e.getPutawayQuantity()));
        });

        // 校验明细上架数量与实际上架数量是否相等
        for(PutawayItem item: items){
            if(item.getReceivedQuantity().compareTo(itemPutawayQuantity.getOrDefault(item.getCode(), BigDecimal.ZERO)) != 0){
                throw new ServiceException("上架数量不等于收货数量，无法完成上架确认!");
            }
        }

    }

    /**
     * 校验上架单明细信息，返回｛明细code: 校验成功/失败}
     * @param entity
     * @param oldEntity 数据库中已确认的信息
     * @return
     */
    @Deprecated
    private Map<String, Boolean> validPutawayItemReceiveInfo(Putaway entity, PutawayVO oldEntity) {
        List<PutawayRegister> registers = new ArrayList<>();
        //从数据库中获取已上架确认的数据，并与PC提交的合并、去重（用数据库中的数据做最新数据）
        entity.getPutawayRegisterWithItemVOS().stream().forEach(e->{
            PutawayRegister putawayRegister = new PutawayRegister();
            BeanUtil.copyProperties(e, putawayRegister);
            registers.add(putawayRegister);
        });
        // 数据库中的确认单
        List<PutawayRegister> oldRegisters = new ArrayList<>();
        oldEntity.getPutawayRegisterWithItemVOS().stream().forEach(e->{
            PutawayRegister putawayRegister = new PutawayRegister();
            BeanUtil.copyProperties(e, putawayRegister);
            oldRegisters.add(putawayRegister);
        });
        // 先做差集，再合并
        Map<String, PutawayRegister> oldRegisterMap = oldRegisters.stream().collect(Collectors.toMap(PutawayRegister::getCode, e->e));
        registers.stream().filter(item -> !oldRegisterMap.containsKey(item.getCode())).collect(Collectors.toList());
        registers.addAll(oldRegisters);

        Map<String, Boolean> result;
        result = new HashMap<>();
        // 遍历生成两个Map，一个记录应收数量， 一个累计记录确认上架数量
        Map<String, BigDecimal> putawayReceived;
        putawayReceived = new HashMap<>();
        Map<String, BigDecimal> putawayRegister;
        putawayRegister = new HashMap<>();

        registers.stream().forEach(e->{
            putawayReceived.put(e.getPutawayItemCode(), e.getReceivedQuantity());
            putawayRegister.put(e.getPutawayItemCode(), putawayRegister.getOrDefault(e.getPutawayItemCode(), BigDecimal.ZERO).add(e.getPutawayQuantity()));
        });
        // 数量相等则true，否则false
        putawayReceived.forEach((itemCode, v)->{
            if(v.compareTo(putawayRegister.get(itemCode)) == 0){
                result.put(itemCode, true);
            }else{
                result.put(itemCode, false);
            }
        });

        return result;
    }

    /**
     * 生成库存
     * @param putawayRegisters
     */
    @Transactional(rollbackFor = {Exception.class})
    public void generateAndSaveInventory(List<PutawayRegister> putawayRegisters) {
        String groupCode = putawayRegisters.get(NUM_ZERO).getGroupCode();
        // 根据确认单 获取 上架单明细， 获取上架单
        Putaway putaway = this.getOne(new QueryWrapper<Putaway>().lambda()
                .eq(Putaway::getCode, putawayRegisters.get(0).getPutawayCode())
                .eq(Putaway::getGroupCode,groupCode)
                .eq(Putaway::getDeleted, 0));

        // 确认单对应的明细code去重
        Map<String, Object> itemCodeMap;
        itemCodeMap = new HashMap<>();
        putawayRegisters.forEach(e->itemCodeMap.put(e.getPutawayItemCode(), null));
        List<String> itemCodeList = new ArrayList<>(itemCodeMap.keySet());

        // 查询上架明细的集合，并放到map中，减少之后循环查询的次数
        List<PutawayItemVO> putawayItemVOs = iPutawayItemService.queryListByCodes(itemCodeList,groupCode);
        Map<String, PutawayItemVO> putawayItemMap;
        putawayItemMap = new HashMap<>();
        putawayItemVOs.forEach(e->putawayItemMap.put(e.getCode(), e));

        PutawayItemVO item;
        Inventory sameInventory;
        Inventory inventory;
        // 根据收货单明细分组汇总入库数量
        Map<String, BigDecimal> receiveItemInboundInfo;
        receiveItemInboundInfo = new HashMap<>();
        BigDecimal inboundQuantity = BigDecimal.ZERO;
        // 根据收货登记分组汇总入库数量
        Map<String, BigDecimal> receiveRegisterInboundInfo;
        receiveRegisterInboundInfo = new HashMap<>();

        for (PutawayRegister register: putawayRegisters) {
            receiveItemInboundInfo.put(register.getReceiveItemCode(),
                    receiveItemInboundInfo.getOrDefault(register.getReceiveItemCode(), BigDecimal.ZERO).add(register.getPutawayQuantity()));
            inboundQuantity = inboundQuantity.add(register.getPutawayQuantity());

            receiveRegisterInboundInfo.put(register.getReceiveRegisterCode(),
                    receiveRegisterInboundInfo.getOrDefault(register.getReceiveRegisterCode(), BigDecimal.ZERO).add(register.getPutawayQuantity()));

            // 从map中获取明细信息，减少重复查询
            item = putawayItemMap.get(register.getPutawayItemCode());
            // 根据上架单、上架明细、上架确认生成库存
            inventory = generateInventory(putaway, item, register);

            // 查询是否有相同的库存
            sameInventory = iInventoryService.hasSameInventory(inventory.getLot(), inventory.getGoodsCode(), inventory.getLocation(),
                    inventory.getShipmentCode(), inventory.getGoodsStatus(), inventory.getIsLock(), inventory.getContainerBarCode(), inventory.getGmtStock());

            if(sameInventory != null){
                // 存在相同库存则只需调整库存
                iInventoryService.adjustQuantity(sameInventory.getCode(), inventory.getQuantity());
            }else {
                // 不存在相同库存则需要插入一条新库存信息
                iInventoryService.save(inventory);
                sameInventory = inventory;
            }

            // 记录库存变动日志
            Inventory tempInventory = iInventoryService.getOne(new QueryWrapper<Inventory>().lambda().eq(Inventory::getCode, item.getTempInventoryCode()).eq(Inventory::getGroupCode,groupCode));
            iInventoryRecordService.insertRecord(tempInventory, putaway.getCode(), inventory.getQuantity().negate(), InventoryRecordTypeEnum.INBOUND.getValue());
            iInventoryRecordService.insertRecord(sameInventory, putaway.getCode(), inventory.getQuantity(), InventoryRecordTypeEnum.INBOUND.getValue());

            // 将临时库存中的数量减掉
            updateTempInventory(item, inventory);

            // 更新上架确认单中的存货时间、库存批次号信息
            String lot = inventory.getLot();
            // 更新上架确认明细中的批次、存货日期
            PutawayRegister putawayRegister = iPutawayRegisterService.getOne(new QueryWrapper<PutawayRegister>().lambda().eq(PutawayRegister::getCode, register.getCode())
            .eq(PutawayRegister::getGroupCode,groupCode));
            putawayRegister.setLot(lot);
            iPutawayRegisterService.updateByCode(putawayRegister);
        }

        //下面方法去掉的原因：1.生成入库单的时候，批号和存货日期已经生成 2.压测的时候，这个地方出现死锁问题
        // 更新入库明细中的批号、存货日期
//        iInboundItemService.updateInventoryInfoByPutawayCode(putaway.getCode());

        // 更新收货单入库数量

        iReceiveService.update(new UpdateWrapper<Receive>().lambda().eq(Receive::getCode,  putaway.getReceiveCode())
                        .eq(Receive::getGroupCode,groupCode)
                        .setSql(" inbound_quantity = inbound_quantity + " + inboundQuantity)
                        .setSql(" putaway_quantity = putaway_quantity + " + inboundQuantity));


        iReceiveItemService.update(new UpdateWrapper<ReceiveItem>().lambda().eq(ReceiveItem::getReceiveCode, putaway.getReceiveCode()).eq(ReceiveItem::getGroupCode,groupCode)
                .set(ReceiveItem::getInboundQuantity, BigDecimal.ZERO));
        List<PutawayRegister> dbPutawayRegisters = iPutawayRegisterService.list(new QueryWrapper<PutawayRegister>().lambda().eq(PutawayRegister::getPutawayCode, putaway.getCode()).eq(PutawayRegister::getGroupCode,groupCode));

        // 更新收货确认单，先更新批号、存货日期，再更新入库数量
        iReceiveRegisterService.updateInventoryInfoByPutawayCode(putaway.getCode(),groupCode);

        // 更新收货明细数量
        List<PutawayItem> putawayItems = iPutawayItemService.list(new QueryWrapper<PutawayItem>().lambda().eq(PutawayItem::getPutawayCode, putaway.getCode()).eq(PutawayItem::getGroupCode,groupCode));
        putawayItems.forEach(e->{
            iReceiveItemService.update(new UpdateWrapper<ReceiveItem>().lambda().eq(ReceiveItem::getCode, e.getReceiveItemCode()).eq(ReceiveItem::getGroupCode,groupCode)
                .setSql(" inbound_quantity = inbound_quantity + " + e.getPutawayQuantity())
            );
        });


    }

    /**
     * 减掉临时库存的信息
     * @param item
     * @param inventory
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public Result updateTempInventory(PutawayItemVO item, Inventory inventory) {
        // 负数减掉临时库存的数量
        iInventoryService.reduceQuantity(item.getTempInventoryCode(), inventory.getQuantity());
        return Result.ok();
    }

    /**
     * 根据上架单、上架明细、上架确认生成库存明细
     * @param putaway
     * @param item
     * @param register
     * @return
     */
    public Inventory generateInventory(Putaway putaway, PutawayItemVO item, PutawayRegister register){
        Inventory inventory = new Inventory();
        BeanUtil.copyProperties(register, inventory);
        inventory.setCode(IdUtil.simpleUUID());
        inventory.setWarehouseCode(putaway.getWarehouseCode());
        inventory.setWarehouseSpaceCode(register.getSpaceCode());
        inventory.setShipmentCode(putaway.getShipmentCode());
        inventory.setShipmentName(putaway.getShipmentName());
        inventory.setGoodsCode(item.getGoodsCode());
        inventory.setGoodCode(item.getGoodCode());
        inventory.setGoodsName(item.getGoodsName());
        inventory.setGoodsBarCode(item.getGoodsBarCode());
        // 保存商品基本单位
        inventory.setGoodsUnit(register.getBasicUnit());
        inventory.setUnitName(register.getBasicUnitName());
        // 库存数量 = 上架数量*最小单位转换件装量
        inventory.setQuantity(register.getPutawayQuantity().multiply(register.getUnitConvertQuantity()));
        inventory.setIsLock(0);
        inventory.setDeleted(0);
        inventory.setGmtStock(register.getGmtStock());
        inventory.setCreatedBy(UserUtil.getCode());
        inventory.setCreatedName(partyCache.translate(UserUtil.getCode()));
        // 如果不是托盘，则库存上不会记录容器号
        if (!ContainerTypeEnum.PALLET.getValue().equals(register.getContainerType())) {
            inventory.setContainerBarCode(StrUtil.EMPTY);
        }

        // 判断是否需要将收货批号打到库存上
        Map<String, Object> goodsMap = goodsCache.get(inventory.getGoodsCode());
        String lotNumber = goodsMap.getOrDefault("lotNumber", "").toString();
        Map<String, Object> batchRuleMap = batchRuleCache.get(lotNumber);
        if(batchRuleMap != null){
            String lotFlag = batchRuleMap.getOrDefault("lot", "0").toString();
            if(NUM_ONE.toString().equals(lotFlag)){
                inventory.setReceiveLot(register.getReceiveLot());
            } else {
                inventory.setReceiveLot(StrUtil.EMPTY);
            }
        }

        //收货登记明细里的有效期为1时，有两种情况形成的，一是确实为1，二是为空时设置的一个默认值
        if (register.getExpirationQuantity().compareTo(BigDecimal.ONE) == NumConst.NUM_ZERO) {
            //找到对应的商品
            Goods goods = goodsCache.getObj(register.getGoodsCode());
            inventory.setExpirationQuantity(goods.getQuality());
        } else {
            inventory.setExpirationQuantity(register.getExpirationQuantity());
        }
        // 生成库存批次
        String lot = OrderIdGeneratorUtil.generatorLot(inventory);
        inventory.setLot(lot);
        // 生成字段都包含的库存批次规则
        inventory.setFullLot(OrderIdGeneratorUtil.generatorFullLot(inventory));

        return inventory;
    }


    /**
     * 生成入库单信息
     * @param putaway
     * @param putawayRegisters
     * @return
     */
    public Inbound generateAndSaveInboundInfo(Putaway putaway, List<PutawayRegister> putawayRegisters,String creator,String creatorName){
        String groupCode = putaway.getGroupCode();
        Receive receive = iReceiveService.getOne(new QueryWrapper<Receive>().lambda().eq(Receive::getCode, putaway.getReceiveCode()).eq(Receive::getGroupCode,groupCode));
        // 生成入库单
        Inbound inbound = new Inbound();
        // 入库单号  RK+货主编码+yyyyMMdd+四位流水号
        inbound.setCode(OrderIdGeneratorUtil.generatorOrderId(OrderIdGeneratorUtil.OrderTypeEnum.RK, putaway.getShipmentCode(),groupCode));
        inbound.setWarehouseCode(putaway.getWarehouseCode());
        inbound.setShipmentCode(putaway.getShipmentCode());
        inbound.setShipmentName(putaway.getShipmentName());
        inbound.setGroupCode(groupCode);
        //  来源单号，这里取上架单的收货单号
        inbound.setSourceCode(putaway.getReceiveCode());
        //  单据类型
        inbound.setType(receive.getType());
        //  订单日期，取收货单创建时间
        inbound.setGmtOrder(receive.getGmtCreated());
        //  计划数量， 取上架单总数量
        inbound.setPlanQuantity(putaway.getTotalQuantity());
        //  入库数量，取上架单数量
        inbound.setInboundQuantity(putaway.getPutawayQuantity());
        inbound.setStatus(InboundStatusEnum.FINISH_IN.getValue());
        inbound.setRemarks(putaway.getRemarks());
        inbound.setDeleted(0);
        inbound.setCreatedBy(creator);
        inbound.setCreatedName(creatorName);
        inbound.setPutawayCode(putaway.getCode());
        iInboundService.save(inbound);

        List<InboundItem> inboundItems = new ArrayList<>();

        // 生成入库单明细
        for (PutawayRegister register : putawayRegisters) {
            InboundItem inboundItem = new InboundItem();
            BeanUtil.copyProperties(register, inboundItem);
            inboundItem.setInboundCode(inbound.getCode());
            inboundItem.setPutawayRegisterCode(register.getCode());
            inboundItem.setInboundQuantity(register.getPutawayQuantity());
            inboundItem.setStatus(InboundStatusEnum.FINISH_IN.getValue());
            inboundItem.setDeleted(0);
            inboundItems.add(inboundItem);
            iInboundItemService.save(inboundItem);
        }



        return inbound;
    }

    @Async
    @Override
    public void orderConfirm(Inbound inbound){
        //采购入库，调拨入库，其他入库
        if (StrUtil.equalsAny(inbound.getType(),"0","3","6")) {
            log.info("采购入库单确认：{}",inbound);
            entryOrderConfirm(inbound);
        }
        if ("1".equals(inbound.getType())) {
            log.info("退货入库单确认：{}",inbound);
            returnOrderConfirm(inbound);
        }
    }

    /***
     * @description
     * 推送奇门入库单确认信息
     * @author rfwang
     * @date 2021/02/23
     **/
    private void entryOrderConfirm(Inbound inbound) {
        String groupCode = inbound.getGroupCode();
        EntryorderConfirmRequest req = new EntryorderConfirmRequest();
        List<EntryorderConfirmRequest.OrderLine> orderLines = new ArrayList<>();
        List<InboundItem> inboundItems = iInboundItemService.list(new QueryWrapper<InboundItem>().lambda().eq(InboundItem::getInboundCode,inbound.getCode())
                .eq(InboundItem::getGroupCode,groupCode)
                .eq(InboundItem::getDeleted, NUM_ZERO));

        log.info("入库单确认，获取入库单明细:{}",inboundItems);
        Receive receive = iReceiveService.getOne(new QueryWrapper<Receive>().lambda().eq(Receive::getCode, inbound.getSourceCode())
                .eq(Receive::getGroupCode,groupCode)
                .eq(Receive::getDeleted, NUM_ZERO));
        log.info("构造奇门入库单确认数据,入库单号：{},发货单信息：{}",inbound.getCode(),receive);
        if(StrUtil.isBlank(receive.getEntryOrderCode())){
            log.info("入库单不是奇门订单，无需确认。{}",receive.getCode());
            return;
        }
        Map<String,Object> warehouseMap= warehouseCache.get(inbound.getWarehouseCode());

        //构建奇门入库单详情
        EntryorderConfirmRequest.EntryOrder entryOrder = new EntryorderConfirmRequest.EntryOrder();
        //业务类型(SCRK=生产入库;LYRK=领用入库;CCRK=残次品入库;CGRK=采购入库;DBRK=调拨入库;QTRK=其他入库;B2BRK=B2B入 库;XNRK=虚拟入库;只传英文编码)
        //注意：文档中对应的是orderType字段，实际上对应的是entryOrderType字段
        if(inbound.getType().equals("0")){
            entryOrder.setEntryOrderType("CGRK");
        }
        if(inbound.getType().equals("3")){
            entryOrder.setEntryOrderType("DBRK");
        }
        if(inbound.getType().equals("6")){
            entryOrder.setEntryOrderType("QTRK");
        }


        entryOrder.setEntryOrderCode(receive.getSourceCode());
        //	货主编码
        entryOrder.setOwnerCode(inbound.getShipmentCode());
        //仓库编码(统仓统配等无需ERP指定仓储编码的情况填OTHER)
        entryOrder.setWarehouseCode(MapUtil.getStr(warehouseMap,"serialNumber"));
        entryOrder.setWarehouseName(warehouseCache.translate(inbound.getWarehouseCode()));
        //外部业务编码(消息ID;用于去重;ISV对于同一请求;分配一个唯一性的编码。用来保证因为网络等原因导致重复传输;请求 不会被重复处理)
        entryOrder.setOutBizCode(inbound.getCode());
        //	入库单状态(NEW-未开始处理;ACCEPT-仓库接单;PARTFULFILLED-部分收货完成;FULFILLED-收货完成;EXCEPTION-异 常;CANCELED-取消;CLOSED-关闭;REJECT-拒单;CANCELEDFAIL-取消失败;只传英文编码)
        //入库数量和计划数量做对比，如果计划数量大于入库数量，就认为是部分收获，否则，认为是收获完成
        if (receive.getTotalQuantity().compareTo(receive.getInboundQuantity()) > NUM_ZERO) {
            entryOrder.setStatus("PARTFULFILLED");
        } else {
            entryOrder.setStatus("FULFILLED");
        }
        //店铺名称
        //TODO 店铺名称和店铺code如何赋值
        //entryOrder.setShopNick("奇门测试店铺");
        //店铺编码
        //entryOrder.setShopCode("qimenTestShop");

        //相同的商品进行合并
        List<InboundItem> inboundItemAfterCombines = combineInboundItemByGoods(inboundItems);

        for (InboundItem inboundItem : inboundItemAfterCombines) {
            ReceiveItem receiveItem = iReceiveItemService.getOne(new QueryWrapper<ReceiveItem>().lambda()
                    .eq(ReceiveItem::getGroupCode,groupCode)
                    .eq(ReceiveItem::getCode, inboundItem.getReceiveItemCode()).eq(ReceiveItem::getDeleted, NUM_ZERO));
            //构建奇门入库单orderLine对象详情
            EntryorderConfirmRequest.OrderLine orderLine = new EntryorderConfirmRequest.OrderLine();
            orderLine.setOwnerCode(inbound.getShipmentCode());
            orderLine.setItemCode(inboundItem.getGoodCode());
            orderLine.setItemName(inboundItem.getGoodsName());
            orderLine.setUnit(inboundItem.getGoodsUnitName());
            orderLine.setPlanQty(receiveItem.getPlanQuantity().longValue());
            orderLine.setActualQty(inboundItem.getInboundQuantity().longValue());
            List<InboundItem> inboundItemList = inboundItems.stream().filter(e -> e.getGoodsCode().equals(inboundItem.getGoodsCode())).collect(Collectors.toList());
            List<EntryorderConfirmRequest.Batch> batchs = inboundItemList.stream().map(e -> {
                EntryorderConfirmRequest.Batch batch = new EntryorderConfirmRequest.Batch();
                //对应库存批次,拓展2对应的商品批次
                if (StrUtil.isNotEmpty(e.getExtendTwo())) {
                    batch.setBatchCode(e.getExtendTwo());
                } else {
                    Inventory inventory = new Inventory();
                    BeanUtil.copyProperties(e,inventory);
                    String lot = OrderIdGeneratorUtil.generatorLot(inventory);
                    batch.setBatchCode(lot);
                }

                if (null != e.getGmtManufacture()) {
                    batch.setProductDate(e.getGmtManufacture().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                }
                if (null != e.getGmtExpire()) {
                    batch.setExpireDate(e.getGmtExpire().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                }

                //对应生成批号
                batch.setProduceCode(e.getExtendOne());
                //默认正品
                batch.setInventoryType("ZP");
                batch.setActualQty(e.getInboundQuantity().longValue());
                return batch;
            }).collect(Collectors.toList());
            orderLine.setBatchs(batchs);
            LocalDateTime gmtManufacture = inboundItem.getGmtManufacture();
            LocalDateTime getGmtExpire = inboundItem.getGmtExpire();
            if (null != gmtManufacture) {
                orderLine.setProductDate(gmtManufacture.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            if (null != getGmtExpire) {
                orderLine.setExpireDate(getGmtExpire.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }

            orderLine.setProductCode(inboundItem.getExtendOne());
            orderLine.setBatchCode(inboundItem.getReceiveLot());
            orderLines.add(orderLine);
        }
        log.info("入库单确认明细,{}",JSONUtil.toJsonStr(orderLines));
        req.setEntryOrder(entryOrder);
        req.setOrderLines(orderLines);
        req.setCustomerId(receive.getCustomerId());

        log.info("入库单确认信息,{}",JSONUtil.toJsonStr(req));
        try {
            QimenClient client = new DefaultQimenClient(url, appkey, secret);
            log.info("入库单确认请求数据:{}", JSONUtil.toJsonStr(req));
            EntryorderConfirmResponse rsp = client.execute(req);
            log.info("入库单确认返回：{}" , rsp.getMessage());
        } catch (Exception e) {
            log.error("入库单确认发生异常：", e);
        }


    }

    /***
     * @description
     * 推送奇门入库单确认信息(退货)
     * @author rfwang
     * @date 2021/02/23
     **/
    private void returnOrderConfirm(Inbound inbound) {
        String groupCode = inbound.getGroupCode();
        ReturnorderConfirmRequest req = new ReturnorderConfirmRequest();
        List<ReturnorderConfirmRequest.OrderLine> orderLines = new ArrayList<>();
        List<InboundItem> inboundItems = iInboundItemService.list(new QueryWrapper<InboundItem>().lambda().eq(InboundItem::getInboundCode,inbound.getCode())
                .eq(InboundItem::getGroupCode,groupCode)
                .eq(InboundItem::getDeleted, NUM_ZERO));
        log.info("退货入库确认，获取入库单明细:{}",inboundItems);
        Receive receive = iReceiveService.getOne(new QueryWrapper<Receive>().lambda().eq(Receive::getCode, inbound.getSourceCode())
                .eq(Receive::getGroupCode,groupCode)
                .eq(Receive::getDeleted, NUM_ZERO));
        log.info("退货入库确认，获取收货单信息:{}",receive);
        Map<String,Object> warehouseMap= warehouseCache.get(inbound.getWarehouseCode());

        //构建奇门入库单详情
        ReturnorderConfirmRequest.ReturnOrder entryOrder = new ReturnorderConfirmRequest.ReturnOrder();
        entryOrder.setReturnOrderCode(receive.getSourceCode());
        //	货主编码
        entryOrder.setOwnerCode(inbound.getShipmentCode());
        //仓库编码(统仓统配等无需ERP指定仓储编码的情况填OTHER)
        entryOrder.setWarehouseCode(MapUtil.getStr(warehouseMap,"serialNumber"));
        //外部业务编码(消息ID;用于去重;ISV对于同一请求;分配一个唯一性的编码。用来保证因为网络等原因导致重复传输;请求 不会被重复处理)
        entryOrder.setOutBizCode(inbound.getCode());

        //相同的商品进行合并
        List<InboundItem> inboundItemAfterCombines = combineInboundItemByGoods(inboundItems);
        for (InboundItem inboundItem : inboundItemAfterCombines) {
            ReceiveItem receiveItem = iReceiveItemService.getOne(new QueryWrapper<ReceiveItem>().lambda()
                    .eq(ReceiveItem::getGroupCode,groupCode)
                    .eq(ReceiveItem::getCode, inboundItem.getReceiveItemCode()).eq(ReceiveItem::getDeleted, NUM_ZERO));
            //构建奇门入库单orderLine对象详情
            ReturnorderConfirmRequest.OrderLine orderLine = new ReturnorderConfirmRequest.OrderLine();
            orderLine.setOwnerCode(inbound.getShipmentCode());
            orderLine.setItemCode(inboundItem.getGoodCode());
            orderLine.setItemName(inboundItem.getGoodsName());
            orderLine.setPlanQty(receiveItem.getPlanQuantity().longValue());
            orderLine.setActualQty(inboundItem.getInboundQuantity().intValue()+"");
            List<InboundItem> inboundItemList = inboundItems.stream().filter(e -> e.getGoodsCode().equals(inboundItem.getGoodsCode())).collect(Collectors.toList());
            List<ReturnorderConfirmRequest.Batch> batchs = inboundItemList.stream().map(e -> {
                ReturnorderConfirmRequest.Batch batch = new ReturnorderConfirmRequest.Batch();
                //对应库存批次,拓展2对应的商品批次
                if (StrUtil.isNotEmpty(e.getExtendTwo())) {
                    batch.setBatchCode(e.getExtendTwo());
                } else {
                    Inventory inventory = new Inventory();
                    BeanUtil.copyProperties(e,inventory);
                    String lot = OrderIdGeneratorUtil.generatorLot(inventory);
                    batch.setBatchCode(lot);
                }
                if (null != e.getGmtManufacture()) {
                    batch.setProductDate(e.getGmtManufacture().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                }
                if (null != e.getGmtExpire()) {
                    batch.setExpireDate(e.getGmtExpire().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                }
                //对应生成批号
                batch.setProduceCode(e.getExtendOne());
                //默认正品
                batch.setInventoryType("ZP");
                batch.setActualQty(e.getInboundQuantity().longValue());
                return batch;
            }).collect(Collectors.toList());
            orderLine.setBatchs(batchs);
            LocalDateTime gmtManufacture = inboundItem.getGmtManufacture();
            LocalDateTime getGmtExpire = inboundItem.getGmtExpire();
            if (null != gmtManufacture) {
                orderLine.setProductDate(gmtManufacture.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            if (null != getGmtExpire) {
                orderLine.setExpireDate(getGmtExpire.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            orderLine.setProductCode(inboundItem.getExtendOne());
            orderLine.setBatchCode(inboundItem.getReceiveLot());
            orderLines.add(orderLine);
        }
        req.setReturnOrder(entryOrder);
        req.setOrderLines(orderLines);
        req.setCustomerId(receive.getCustomerId());
        log.info("退货入库确认，奇门入库单确认信息:{}",JSONUtil.toJsonStr(req));
        //returnInboundConfirmSender.sendConfirm(req);
        try {
            QimenClient client = new DefaultQimenClient(url, appkey, secret);
            ReturnorderConfirmResponse rsp = client.execute(req);
            log.info("退货入库确认返回：{}" , rsp.getMessage());
        } catch (Exception e) {
            log.error("退货入库确认发生异常：", e);
        }
    }

    private List<InboundItem> combineInboundItemByGoods(List<InboundItem> inboundItems) {
        //相同的商品进行合并
        Map<String,List<InboundItem>> listMap = inboundItems.stream().collect(Collectors.groupingBy(InboundItem::getGoodsCode));
        if (inboundItems.size() == listMap.entrySet().size()) {
            return inboundItems;
        }
        List<InboundItem> inboundItemList = Lists.newArrayList();
        for (Map.Entry<String,List<InboundItem>> entry : listMap.entrySet()) {
            if (entry.getValue().size() > 1) {
                BigDecimal totalInboundQuantity = entry.getValue().stream().map(InboundItem::getInboundQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
                InboundItem inboundItem = entry.getValue().get(NUM_ZERO);
                InboundItem inboundItemNew = new InboundItem();
                BeanUtil.copyProperties(inboundItem,inboundItemNew);
                inboundItemNew.setInboundQuantity(totalInboundQuantity);
                inboundItemList.add(inboundItemNew);
            } else {
                inboundItemList.addAll(entry.getValue());
            }
        }
        return inboundItemList;
    }


    /***
     * @description
     * 生成仓储合同定时任务
     * @author xuyang
     * @date 2020/12/28 14:15
     **/
    @Transactional(rollbackFor = {Exception.class})
    public void generateContractScheduling(Inbound inbound, InboundItem item) {
        // 基本单位下商品的重量
        BigDecimal basicUnitWeight = goodsUnitConversionCache.getBasicUnitWeight(item.getGoodsCode());

        ContractSchedulingInventoryDTO contractSchedulingInventoryDTO = new ContractSchedulingInventoryDTO();
        contractSchedulingInventoryDTO.setInboundCode(inbound.getCode());
        contractSchedulingInventoryDTO.setWarehouseCode(inbound.getWarehouseCode());
        contractSchedulingInventoryDTO.setShipmentCode(inbound.getShipmentCode());
        contractSchedulingInventoryDTO.setShipmentName(inbound.getShipmentName());
        contractSchedulingInventoryDTO.setGoodsCode(item.getGoodsCode());
        contractSchedulingInventoryDTO.setGoodCode(item.getGoodCode());
        contractSchedulingInventoryDTO.setGoodsBarCode(item.getGoodsBarCode());
        contractSchedulingInventoryDTO.setGoodsName(item.getGoodsName());
        contractSchedulingInventoryDTO.setQuantity(item.getInboundQuantity());
        contractSchedulingInventoryDTO.setWeight(item.getInboundQuantity().multiply(basicUnitWeight));
        contractSchedulingInventoryDTO.setReceiveLot(item.getReceiveLot());
        contractSchedulingInventoryDTO.setGmtInboundCreated(inbound.getGmtCreated().toLocalDate());
        contractSchedulingInventoryDTO.setGroupCode(UserUtil.getBranchCode());

        iContractService.scatteredGenerateBillingSchedule(contractSchedulingInventoryDTO);
    }

    /**
     * @description
     * XYTODO TODO 入库单明细生成作业费
     * @author xuyang
     * @date 2020/12/28 13:13
     * @param inbound:
     * @param item:
     **/
    @Transactional(rollbackFor = {Exception.class})
    public void generateOperationCost(Inbound inbound, InboundItem item) {
        // 出库生成作业费
        OperationCostSourceDataDTO sourceDataDTO = new OperationCostSourceDataDTO();
        BeanUtils.copyProperties(inbound,sourceDataDTO);
        sourceDataDTO.setType(OrderIdGeneratorUtil.OrderTypeEnum.RK);
        sourceDataDTO.setSourceCode(inbound.getCode());
        sourceDataDTO.setGoodsCode(item.getGoodsCode());
        sourceDataDTO.setGoodCode(item.getGoodCode());
        sourceDataDTO.setGoodsName(item.getGoodsName());
        sourceDataDTO.setQuantity(item.getInboundQuantity());
        sourceDataDTO.setReceiveLot(item.getReceiveLot());
        // 入库单明细已经打散成基本单位了，那总重量是根据基本单位计算？
        BigDecimal basicUnitWeight = goodsUnitConversionCache.getBasicUnitWeight(item.getGoodsCode());
        // 明细总重量 = 基本单位下定义的单个重量 * 入库明细数量
        sourceDataDTO.setWeight(item.getInboundQuantity().multiply(basicUnitWeight));

        // 明细对应的库位应该只会有一个
        sourceDataDTO.setLocationCount(BigDecimal.ONE);
        sourceDataDTO.setGmtOrderCreated(inbound.getGmtCreated().toLocalDate());
        iExpenseDetailService.generateOperationCost(sourceDataDTO);
    }


    /**
     * 更新上架单下发状态
     *
     * @param code
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void updateIssueStatus(String code, String groupCode) {
        this.update(new UpdateWrapper<Putaway>().lambda().eq(Putaway::getCode, code)
                .eq(Putaway::getGroupCode,groupCode)
                .set(Putaway::getIssue, IssueStatusEnum.ISSUED));
    }

    @Override
    public Result getPutawayInfo(WmsTaskDTO wmsTaskDTO){
        List<PutawayItem> putawayItemList = Collections.emptyList();
        List<WmsTaskItem> wmsTaskItemList = wmsTaskItemService.list(new QueryWrapper<WmsTaskItem>().lambda().eq(WmsTaskItem::getTaskCode, wmsTaskDTO.getCode()).eq(WmsTaskItem::getGroupCode,UserUtil.getBranchCode()));
        wmsTaskItemList.forEach(item -> {
            putawayItemList.add(iPutawayItemService.getOne(new QueryWrapper<PutawayItem>().lambda().eq(PutawayItem::getCode, item.getSourceCode()).eq(PutawayItem::getGroupCode,UserUtil.getBranchCode())));
        });

        return null;
    }

    /**
     * @param code           :
     * @param registerStatus :
     * @description 更新上架单已上架数量
     * @author xuyang
     * @date 2020/10/30 16:21
     **/
    @Override
    public int updateRegisterQuantity(String code, String registerStatus) {
        return this.baseMapper.updateRegisterQuantity(code, registerStatus,UserUtil.getBranchCode());
    }

    /**
     * 普通上架 详情
     * @param wmsTaskDTO
     * @return
     */
    @Override
    public Result putawayDetail(WmsTaskDTO wmsTaskDTO) {
        String groupCode = UserUtil.getBranchCode();
        wmsTaskDTO.setTaskType(WmsTaskTypeEnum.PUTAWAY.getValue());
        //获取上架任务列表
        List<WmsTaskVO> wmsTaskVOList = iWmsTaskService.queryList(wmsTaskDTO);
        if(IterUtil.isEmpty(wmsTaskVOList)) {
            return Result.ok().data(wmsTaskVOList);
        }

        if(IterUtil.isNotEmpty(wmsTaskVOList)){
            // 翻译供应商
            wmsTaskVOList.forEach(e->{
                if(StrUtil.isNotBlank(e.getSupplierCode())) {
                    e.setSupplierName(supplierCache.translate(e.getSupplierCode()));
                }
            });
        }

        // 如果有多条数据 直接返回
        if(wmsTaskVOList.size() > NUM_ONE) {
            return Result.ok().data(wmsTaskVOList.get(NUM_ZERO));
        }
        //上架单号
        String putawayCode = wmsTaskVOList.get(NUM_ZERO).getSourceCode();
        //获取上架任务明细详情
        List<WmsTaskItem> wmsTaskItemList = wmsTaskItemService.list(new QueryWrapper<WmsTaskItem>().lambda().select(WmsTaskItem::getSourceCode)
                .eq(WmsTaskItem::getGroupCode,groupCode)
                .eq(WmsTaskItem::getTaskCode, wmsTaskVOList.get(NUM_ZERO).getCode()));
        //获取上架明细标识
        List<String> putawayItemCodes = wmsTaskItemList.stream().map(WmsTaskItem::getSourceCode).collect(Collectors.toList());
        if(wmsTaskDTO.getPutawayStatus().equals(NUM_ZERO.toString())) {
            List<PutawayItemVO> putawayItemVOList = null;
            // 商品条码不为空时才根据商品条码过滤
            if (StrUtil.isNotBlank(wmsTaskDTO.getGoodsBarCode())) {

                String goodsCode = "";
                Putaway putaway = baseMapper.selectOne(new LambdaQueryWrapper<Putaway>().select(Putaway::getShipmentCode).eq(Putaway::getCode, putawayCode).eq(Putaway::getGroupCode,groupCode));
                if (putaway != null && StrUtil.isNotBlank(putaway.getShipmentCode())) {
                    goodsCode = goodsPnService.getGoodsCode(putaway.getShipmentCode(), wmsTaskDTO.getGoodsBarCode());
                }

                if (StrUtil.isNotBlank(goodsCode)) {
                    String finalGoodsCode = goodsCode;
                    putawayItemVOList = iPutawayItemService.queryListByCodes(putawayItemCodes,groupCode).stream()
                            .filter(item -> item.getGoodsCode().contains(finalGoodsCode) && ("0".equals(item.getStatus()) || "1".equals(item.getStatus()) || "2".equals(item.getStatus()))).collect(Collectors.toList());
                }
            }else{
                putawayItemVOList = iPutawayItemService.queryListByCodes(putawayItemCodes,groupCode).stream()
                        .filter(item -> "0".equals(item.getStatus()) || "1".equals(item.getStatus()) )
                        .collect(Collectors.toList());
            }
            if(IterUtil.isEmpty(putawayItemVOList)){
                log.error("找不到上架信息：{}",JSONUtil.toJsonStr(wmsTaskDTO));
                wmsTaskVOList.get(NUM_ZERO).setItems(putawayItemVOList);
                return Result.ok().data(wmsTaskVOList);
            }
            putawayItemVOList.forEach(e-> {
                e.setTaskCode(wmsTaskDTO.getCode());
                e.setRecommendLocationName(locationCache.translate(e.getRecommendLocation()));
            });
            // 添加批次规则
            if (IterUtil.isNotEmpty(putawayItemVOList)) {
                putawayItemVOList.forEach(item -> {
                    Map<String, Object> goodsCacheMap = goodsCache.get(item.getGoodsCode());
                    Map<String, Object> batchRuleMap = batchRuleCache.get((String) goodsCacheMap.get(LOT_NUMBER));
                    item.setBatchRule(batchRuleMap);
                });
            }
            wmsTaskVOList.get(NUM_ZERO).setItems(putawayItemVOList);
        }

        if("1".equals(wmsTaskDTO.getPutawayStatus())) {
            List<PutawayRegisterVO> putawayRegisterVOList = iPutawayRegisterService.queryListByCodes(putawayItemCodes);
            putawayRegisterVOList.stream().forEach(e-> {
                e.setRecommendLocationName(locationCache.translate(e.getRecommendLocation()));
            });
            // 添加批次规则
            if (IterUtil.isNotEmpty(putawayRegisterVOList)) {
                putawayRegisterVOList.stream().forEach(item -> {
                    Map<String, Object> goodsCacheMap = goodsCache.get(item.getGoodsCode());
                    Map<String, Object> batchRuleMap = batchRuleCache.get((String) goodsCacheMap.get(LOT_NUMBER));
                    item.setBatchRule(batchRuleMap);
                });
        }
            wmsTaskVOList.get(NUM_ZERO).setItems(putawayRegisterVOList);
        }

        return Result.ok().data(wmsTaskVOList);
    }

    /**
     * 根据上架确认单信息，更新收货确认单、收货明细、收货单的上架信息
     *
     * @param register
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void refreshReceivePutawayQuantity(PutawayRegister register) {
        iReceiveRegisterService.refreshPutawayQuantity(register.getReceiveRegisterCode());
        iReceiveItemService.refreshPutawayQuantity(register.getReceiveItemCode());
        ReceiveItem receiveItem = iReceiveItemService.getOne(new QueryWrapper<ReceiveItem>().lambda()
                .eq(ReceiveItem::getCode, register.getReceiveItemCode())
        .eq(ReceiveItem::getGroupCode,UserUtil.getBranchCode()));
        iReceiveService.refreshPutawayQuantity(receiveItem.getReceiveCode());
    }

    /**
     * 根据上架确认单信息，更新收货确认单、收货明细、收货单的上架和入库信息
     *
     * @param register
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void refreshReceivePutawayAndInboundQuantity(PutawayRegister register) {
        iReceiveRegisterService.refreshPutawayAndInboundQuantity(register.getReceiveRegisterCode());
        iReceiveItemService.refreshPutawayAndInboundQuantity(register.getReceiveItemCode());
        ReceiveItem receiveItem = iReceiveItemService.getOne(new QueryWrapper<ReceiveItem>().lambda()
                .eq(ReceiveItem::getCode, register.getReceiveItemCode()));
        iReceiveService.refreshPutawayAndInboundQuantity(receiveItem.getReceiveCode(),receiveItem.getGroupCode());
    }

    /**
     * 根据上架确认单信息，更新调拨单的入库数量
     *
     * @param register
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void refreshAllocationInboundQuantity(PutawayRegister register) {
        ReceiveItem receiveItem = iReceiveItemService.getOne(new QueryWrapper<ReceiveItem>().lambda().eq(ReceiveItem::getCode,register.getReceiveItemCode()).eq(ReceiveItem::getGroupCode,UserUtil.getBranchCode()));
        Receive receive = iReceiveService.getOne(new QueryWrapper<Receive>().lambda().eq(Receive::getCode, receiveItem.getReceiveCode()).eq(Receive::getGroupCode,UserUtil.getBranchCode()));
        //更新调拨单入库数量
        iReceiveService.updateWmsAllocationInfoByPutaway(receive);
    }

}
